import { IContextDescriptionItem } from '@/apis/chat/interfaces'
import anime from 'animejs'
import { Box, Rect } from 'leafer-ui'
import { ref } from 'vue'
import { emitter } from './emitter'
import { uiItems } from './uiItems'

export const started = ref(false)

export const isAnimation = ref(false)

export const infoText = ref('未开始')

export const config = {
    duration: 300,
}

// 待排序的元素
let globalArr: number[] = []
// 要做动画的rect
let globalRects: Rect[] = []
// 生成器
let generator: AsyncGenerator<undefined, void, unknown> | null = null

// 冒泡排序算法
export const bubbleSort = (arr: number[]) => {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换两个元素的位置
                const temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
    }
}

export const setInfo = (str: string) => {
    // console.log(str)
    infoText.value = str
}

// 生成器函数
export async function* bubbleSortGenerator(arr: number[]) {
    started.value = true
    setInfo(`开始排序`)
    emitter.emit('SORT_START')
    yield
    for (let i = 0; i < arr.length; i++) {
        setInfo(`当前第 ${i} 论`)
        emitter.emit('ROUND_START')
        yield
        for (let j = 0; j < arr.length - i - 1; j++) {
            setInfo(`比较数组的第 ${j} 项和第 ${j + 1} 项`)
            const jRect = globalRects[j]
            const j1Rect = globalRects[j + 1]
            await anime({
                targets: [jRect, j1Rect],
                fill: '#4279e4',
                duration: config.duration,
                easing: 'linear',
                update: () => {
                    jRect.forceUpdate()
                    j1Rect.forceUpdate()
                },
            }).finished
            yield
            if (arr[j] > arr[j + 1]) {
                setInfo(`${arr[j]} 大于 ${arr[j + 1]}，交换位置`)
                emitter.emit('SWAP')
                // 交换两个元素的位置
                const temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp

                const tempRect = globalRects[j]
                globalRects[j] = globalRects[j + 1]
                globalRects[j + 1] = tempRect

                const jx = jRect.x
                const j1x = j1Rect.x

                await Promise.all([
                    anime({
                        targets: jRect,
                        x: j1x,
                        duration: 100,
                        easing: 'linear',
                    }).finished,
                    anime({
                        targets: j1Rect,
                        x: jx,
                        duration: 100,
                        easing: 'linear',
                    }).finished,
                ])
                yield
            }

            await anime({
                targets: [jRect, j1Rect],
                fill: '#ededed',
                duration: config.duration,
                easing: 'linear',
                update: () => {
                    jRect.forceUpdate()
                    j1Rect.forceUpdate()
                },
            })
        }
    }
}

// 初始化
export const init = (arr: number[]) => {
    started.value = false
    globalArr = arr
    // 画布的高度为500，数组中的最大值为4，所以每个元素对应的高度为500/4=125
    const max = Math.max(...arr)
    const unitHeight = 500 / max

    const rects = arr.map((num, i) => {
        const width = 30
        const gap = 10
        const height = num * unitHeight
        return new Box({
            x: i * (width + gap),
            y: 500 - height,
            width,
            height,
            fill: '#ededed',
            children: [
                {
                    tag: 'Text',
                    text: num,
                    width,
                    height,
                    textAlign: 'center',
                    verticalAlign: 'bottom',
                },
            ],
        })
    })

    globalRects = rects
    const container = uiItems.container as Box
    container.clear()
    container.add(rects)
    setTimeout(() => {
        container.app.tree?.zoom('fit')
    }, 1000)
}

// 开始
export const start = () => {
    generator = bubbleSortGenerator(globalArr)
    generator.next()
}

// 下一步
export const next = async () => {
    if (!generator || isAnimation.value) return
    isAnimation.value = true
    const res = await generator.next()
    isAnimation.value = false
    if (res.done) {
        setInfo('结束' + globalArr)
        started.value = false
        emitter.emit('SORT_END')
        return
    }
}

// 运行到结束
export const runToEnd = async () => {
    if (!generator || isAnimation.value) return
    isAnimation.value = true
    const res = await generator.next()
    isAnimation.value = false
    if (res.done) {
        setInfo('结束' + globalArr)
        started.value = false
        emitter.emit('SORT_END')
        return
    }
    await runToEnd()
}

export const getContextDescription: () => IContextDescriptionItem[] = () => {
    return [
        {
            key: 'caseTitle',
            value: '冒泡排序',
        },
        {
            key: 'caseDescription',
            value: '此案例演示了冒泡排序算法的运行过程',
        },
        {
            key: 'caseStatusInfo',
            value: `
待排序元素：${globalArr.join(',')}
当前页面中的提示信息：${infoText.value}
`,
        },
    ]
}
